#define MAGICNUM 0xdec0de
#define BLKSIZE 1024
#define READDISKTIME BLKSIZE/DEVICE_BLOCK_SIZE
#define MAXBLK 4096
#define INODEPERBLK 32
#define MAXFREEBLK (MAXBLK-32-1)
#define MAXFREEINODE (1024-1)

#define MAXPATHDEPTH 12
#define VALID32BITS 0xFFFFFFFF

#define readspblk(buf) readfsblk(0, buf)
#define writespblk(buf) writefsblk(0, buf)

enum{ OPTION_TOUCH = 0,
      OPTION_MKDIR = 1,
      OPTION_CP = 2,
      OPTION_LS = 3,
      OPTION_SHUTDOWN = 4,
      OPTION_UNKNOWN = 5};


typedef struct super_block {
    int magic_num;                  // 幻数
    int free_block_count;           // 空闲数据块数
    int free_inode_count;           // 空闲inode数
    int dir_inode_count;            // 目录inode数
    uint32 block_map[128];            // 数据块占用位图
    uint32 inode_map[32];             // inode占用位图
} sp_block;

enum{ ITEM_DIR = 0, ITEM_FILE = 1, ITEM_ALL = 2};
struct inode {
    uint32 size;              // 文件大小
    uint16 file_type;         // 文件类型（文件/文件夹）
    uint16 link;              // 连接数
    uint32 block_point[6];    // 数据块指针
};

struct dir_item {               // 目录项一个更常见的叫法是 dirent(directory entry)
    uint32 inode_id;          // 当前目录项表示的文件/目录的对应inode
    uint16 valid;             // 当前目录项是否有效 
    uint8 type;               // 当前目录项类型（文件/目录）
    char name[121];             // 目录项表示的文件/目录的文件名/目录名
};

void initfs();
void closefs();

// new item(dir/file)
// @return new inode id, 0 for failure
uint32 touchitem(uint32 parentid, char* name, uint8 type);

// dst_inode must be empty
// TODO: if dst is not an empty space
// TODO: if blk is full
void copyfile(uint32 dst_inode_id, uint32 src_inode_id);

// find item (file/dir)
// @return item inode id, 0 for failure
uint32 finditem_path(char* path, uint32* parent, char* name);

// print all of dir
void printallitem(char* path);


// find item (file/dir) in certain path
// @return item inode id, 0 for failure
// @return uint32* parent: path parent idinode, 0 for failure
uint32 finditem_path(char* path, uint32* parent, char* name);
uint32 finditem_path_simple(char* path);